namespace XEAS.Framework.ShellLib
{
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    public class ApplicationDesktopToolbar : Form
    {
        private readonly uint CallbackMessageID;
        private bool IsAppbarMode;
        private AppBarEdges m_Edge = AppBarEdges.Float;
        private Point m_PrevLocation;
        private Size m_PrevSize;

        public ApplicationDesktopToolbar()
        {
            base.FormBorderStyle = FormBorderStyle.SizableToolWindow;
            this.CallbackMessageID = this.RegisterCallbackMessage();
            if (this.CallbackMessageID == 0)
            {
                throw new Exception("RegisterCallbackMessage failed");
            }
        }

        private void AppbarActivate()
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.hWnd = base.Handle;
            ShellApi.SHAppBarMessage(6, ref structure);
        }

        private IntPtr AppbarGetAutoHideBar(AppBarEdges edge)
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.uEdge = (uint) edge;
            return (IntPtr) ShellApi.SHAppBarMessage(7, ref structure);
        }

        private void AppbarGetTaskbarPos(out ShellApi.RECT taskRect)
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            ShellApi.SHAppBarMessage(5, ref structure);
            taskRect = structure.rc;
        }

        private AppBarStates AppbarGetTaskbarState()
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            return (AppBarStates) ShellApi.SHAppBarMessage(4, ref structure);
        }

        private bool AppbarNew()
        {
            if (this.CallbackMessageID == 0)
            {
                throw new Exception("CallbackMessageID is 0");
            }
            if (this.IsAppbarMode)
            {
                return true;
            }
            this.m_PrevSize = base.Size;
            this.m_PrevLocation = base.Location;
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.hWnd = base.Handle;
            structure.uCallbackMessage = this.CallbackMessageID;
            uint num = ShellApi.SHAppBarMessage(0, ref structure);
            this.IsAppbarMode = num != 0;
            this.SizeAppBar();
            return this.IsAppbarMode;
        }

        private void AppbarQueryPos(ref ShellApi.RECT appRect)
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.hWnd = base.Handle;
            structure.uEdge = (uint) this.m_Edge;
            structure.rc = appRect;
            ShellApi.SHAppBarMessage(2, ref structure);
            appRect = structure.rc;
        }

        private bool AppbarRemove()
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.hWnd = base.Handle;
            uint num = ShellApi.SHAppBarMessage(1, ref structure);
            this.IsAppbarMode = false;
            base.Size = this.m_PrevSize;
            base.Location = this.m_PrevLocation;
            return (num != 0);
        }

        private bool AppbarSetAutoHideBar(bool hideValue)
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.hWnd = base.Handle;
            structure.uEdge = (uint) this.m_Edge;
            structure.lParam = hideValue ? 1 : 0;
            return (ShellApi.SHAppBarMessage(8, ref structure) != 0);
        }

        private void AppbarSetPos(ref ShellApi.RECT appRect)
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.hWnd = base.Handle;
            structure.uEdge = (uint) this.m_Edge;
            structure.rc = appRect;
            ShellApi.SHAppBarMessage(3, ref structure);
            appRect = structure.rc;
        }

        private void AppbarSetTaskbarState(AppBarStates state)
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.lParam = (int) state;
            ShellApi.SHAppBarMessage(10, ref structure);
        }

        private void AppbarWindowPosChanged()
        {
            ShellApi.APPBARDATA structure = new ShellApi.APPBARDATA();
            structure.cbSize = (uint) Marshal.SizeOf(structure);
            structure.hWnd = base.Handle;
            ShellApi.SHAppBarMessage(9, ref structure);
        }

        private void OnAppbarNotification(ref Message msg)
        {
            switch (((AppBarNotifications) ((int) msg.WParam)))
            {
                case AppBarNotifications.StateChange:
                    if ((this.AppbarGetTaskbarState() & AppBarStates.AlwaysOnTop) != 0)
                    {
                        base.TopMost = true;
                        base.BringToFront();
                        break;
                    }
                    base.TopMost = false;
                    base.SendToBack();
                    break;

                case AppBarNotifications.PosChanged:
                    this.SizeAppBar();
                    break;

                case AppBarNotifications.FullScreenApp:
                    if (((int) msg.LParam) != 0)
                    {
                        base.TopMost = false;
                        base.SendToBack();
                        break;
                    }
                    if ((this.AppbarGetTaskbarState() & AppBarStates.AlwaysOnTop) == 0)
                    {
                        base.TopMost = false;
                        base.SendToBack();
                        break;
                    }
                    base.TopMost = true;
                    base.BringToFront();
                    break;

                case AppBarNotifications.WindowArrange:
                    if (((int) msg.LParam) != 0)
                    {
                        base.Visible = false;
                        break;
                    }
                    base.Visible = true;
                    break;
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            this.AppbarRemove();
            base.OnClosing(e);
        }

        protected override void OnLoad(EventArgs e)
        {
            this.m_PrevSize = base.Size;
            this.m_PrevLocation = base.Location;
            base.OnLoad(e);
        }

        private void OnNcHitTest(ref Message msg)
        {
            int num;
            this.DefWndProc(ref msg);
            if ((this.m_Edge == AppBarEdges.Top) && (((int) msg.Result) == 15))
            {
                num = 0;
                num.ToString();
            }
            else if ((this.m_Edge == AppBarEdges.Bottom) && (((int) msg.Result) == 12))
            {
                num = 0;
                num.ToString();
            }
            else if ((this.m_Edge == AppBarEdges.Left) && (((int) msg.Result) == 11))
            {
                num = 0;
                num.ToString();
            }
            else if ((this.m_Edge == AppBarEdges.Right) && (((int) msg.Result) == 10))
            {
                0.ToString();
            }
            else if (((int) msg.Result) == 20)
            {
                0.ToString();
            }
            else
            {
                msg.Result = (IntPtr) 1L;
                return;
            }
            base.WndProc(ref msg);
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            if (this.IsAppbarMode)
            {
                if ((this.m_Edge == AppBarEdges.Top) || (this.m_Edge == AppBarEdges.Bottom))
                {
                    this.m_PrevSize.Height = base.Size.Height;
                }
                else
                {
                    this.m_PrevSize.Width = base.Size.Width;
                }
                this.SizeAppBar();
            }
            base.OnSizeChanged(e);
        }

        private uint RegisterCallbackMessage()
        {
            return ShellApi.RegisterWindowMessage(Guid.NewGuid().ToString());
        }

        private void SizeAppBar()
        {
            ShellApi.RECT appRect = new ShellApi.RECT();
            if ((this.m_Edge == AppBarEdges.Left) || (this.m_Edge == AppBarEdges.Right))
            {
                appRect.top = 0;
                appRect.bottom = SystemInformation.PrimaryMonitorSize.Height;
                if (this.m_Edge == AppBarEdges.Left)
                {
                    appRect.right = this.m_PrevSize.Width;
                }
                else
                {
                    appRect.right = SystemInformation.PrimaryMonitorSize.Width;
                    appRect.left = appRect.right - this.m_PrevSize.Width;
                }
            }
            else
            {
                appRect.left = 0;
                appRect.right = SystemInformation.PrimaryMonitorSize.Width;
                if (this.m_Edge == AppBarEdges.Top)
                {
                    appRect.bottom = this.m_PrevSize.Height;
                }
                else
                {
                    appRect.bottom = SystemInformation.PrimaryMonitorSize.Height;
                    appRect.top = appRect.bottom - this.m_PrevSize.Height;
                }
            }
            this.AppbarQueryPos(ref appRect);
            switch (this.m_Edge)
            {
                case AppBarEdges.Left:
                    appRect.right = appRect.left + this.m_PrevSize.Width;
                    break;

                case AppBarEdges.Top:
                    appRect.bottom = appRect.top + this.m_PrevSize.Height;
                    break;

                case AppBarEdges.Right:
                    appRect.left = appRect.right - this.m_PrevSize.Width;
                    break;

                case AppBarEdges.Bottom:
                    appRect.top = appRect.bottom - this.m_PrevSize.Height;
                    break;
            }
            this.AppbarSetPos(ref appRect);
            base.Location = new Point(appRect.left, appRect.top);
            base.Size = new Size(appRect.right - appRect.left, appRect.bottom - appRect.top);
        }

        protected override void WndProc(ref Message msg)
        {
            if (this.IsAppbarMode)
            {
                if (msg.Msg == this.CallbackMessageID)
                {
                    this.OnAppbarNotification(ref msg);
                }
                else if (msg.Msg == 6)
                {
                    this.AppbarActivate();
                }
                else if (msg.Msg == 0x47)
                {
                    this.AppbarWindowPosChanged();
                }
                else if (msg.Msg == 0x84)
                {
                    this.OnNcHitTest(ref msg);
                    return;
                }
            }
            base.WndProc(ref msg);
        }

        public AppBarEdges Edge
        {
            get
            {
                return this.m_Edge;
            }
            set
            {
                this.m_Edge = value;
                if (value == AppBarEdges.Float)
                {
                    this.AppbarRemove();
                }
                else
                {
                    this.AppbarNew();
                }
                if (this.IsAppbarMode)
                {
                    this.SizeAppBar();
                }
            }
        }

        public enum AppBarEdges
        {
            Left,
            Top,
            Right,
            Bottom,
            Float
        }

        public enum AppBarMessages
        {
            New,
            Remove,
            QueryPos,
            SetPos,
            GetState,
            GetTaskBarPos,
            Activate,
            GetAutoHideBar,
            SetAutoHideBar,
            WindowPosChanged,
            SetState
        }

        public enum AppBarNotifications
        {
            StateChange,
            PosChanged,
            FullScreenApp,
            WindowArrange
        }

        [Flags]
        public enum AppBarStates
        {
            AlwaysOnTop = 2,
            AutoHide = 1
        }

        public enum MousePositionCodes
        {
            HTBORDER = 0x12,
            HTBOTTOM = 15,
            HTBOTTOMLEFT = 0x10,
            HTBOTTOMRIGHT = 0x11,
            HTCAPTION = 2,
            HTCLIENT = 1,
            HTCLOSE = 20,
            HTERROR = -2,
            HTGROWBOX = 4,
            HTHELP = 0x15,
            HTHSCROLL = 6,
            HTLEFT = 10,
            HTMAXBUTTON = 9,
            HTMENU = 5,
            HTMINBUTTON = 8,
            HTNOWHERE = 0,
            HTOBJECT = 0x13,
            HTREDUCE = 8,
            HTRIGHT = 11,
            HTSIZE = 4,
            HTSIZEFIRST = 10,
            HTSIZELAST = 0x11,
            HTSYSMENU = 3,
            HTTOP = 12,
            HTTOPLEFT = 13,
            HTTOPRIGHT = 14,
            HTTRANSPARENT = -1,
            HTVSCROLL = 7,
            HTZOOM = 9
        }

        public enum WM
        {
            ACTIVATE = 6,
            NCHITTEST = 0x84,
            WINDOWPOSCHANGED = 0x47
        }
    }
}

